<template>
	<div class="my-edit-align-line">
		<div
			class="line"
			v-for="item in lineArr"
			:key="item"
			:class="[item.includes('row') ? 'row' : 'col', line['select'].has(item) && 'visible']"
			:style="useComponentStyle(line['select'].get(item))"
		/>
	</div>
</template>

<script setup>
import { setComponentPosition, useComponentStyle } from '@/utils';

// 行横向row（上中下），列竖线col（左中右）
const lineArr = ['rowt', 'rowc', 'rowb', 'coll', 'colc', 'colr'];

// * 线条集合
const line = reactive({
	// 展示线
	select: new Map()
});

// * 吸附判定
function isSorption(selectValue, componentValue) {
	return Math.abs(selectValue - componentValue) <= $store.chart.alignRange;
}

// * 当前目标
const { selectId } = toRefs($store.chart.targetChart),
	selectTarget = computed(() => $store.chart.componentList[$store.chart.fetchTargetIndex()]),
	selectAttr = computed(() => selectTarget.value?.orgConfig.attr || {}),
	// * 画布坐标
	canvasPositionList = computed(() => {
		return {
			id: '0',
			attr: {
				w: $store.chart.editCanvasConfig.width,
				h: $store.chart.editCanvasConfig.height,
				x: 0,
				y: 0,
				offsetX: 0,
				offsetY: 0,
				zIndex: 0
			}
		};
	});

// * 监听鼠标移动
watch(
	() => $store.chart.mousePosition,
	throttle(() => {
		try {
			if (!$store.chart.editCanvas.isDrag || selectId.value.length !== 1) return;

			// 获取目标组件数据
			const selectW = selectAttr.value.w;
			const selectH = selectAttr.value.h;

			// 距离左侧
			const selectLeftX = selectAttr.value.x;
			const selectHalfX = selectLeftX + selectW / 2;
			const selectRightX = selectLeftX + selectW;

			// 距离顶部
			const selectTopY = selectAttr.value.y;
			const selectHalfY = selectTopY + selectH / 2;
			const selectBottomY = selectTopY + selectH;

			line.select.clear();
			// 循环查询所有组件数据
			const componentList = $store.chart.componentList.map((e) => ({
				id: e.id,
				attr: e.orgConfig.attr,
				parentId: e.parentId
			}));
			componentList.push(canvasPositionList.value);

			// 传入画布数据
			let x, y;
			lineArr.forEach((lineItem) => {
				componentList.forEach((component) => {
					// 排除自身
					if (selectId.value[0] === component.id) return;
					const componentW = component.attr.w;
					const componentH = component.attr.h;

					// 距离左侧
					const componentLeftX = component.attr.x;
					const componentHalfX = componentLeftX + componentW / 2;
					const componentRightX = componentLeftX + componentW;

					// 距离顶部
					const componentTopY = component.attr.y;
					const componentHalfY = componentTopY + componentH / 2;
					const componentBottomY = componentTopY + componentH;

					// 横线对比的是 Y
					if (lineItem.includes('rowt')) {
						// 顶部
						if (isSorption(selectTopY, componentTopY)) {
							line.select.set(lineItem, { y: componentTopY });
							y = componentTopY;
						}
						if (isSorption(selectTopY, componentHalfY)) {
							line.select.set(lineItem, { y: componentHalfY });
							y = componentHalfY;
						}
						if (isSorption(selectTopY, componentBottomY)) {
							line.select.set(lineItem, { y: componentBottomY });
							y = componentBottomY;
						}
					}
					if (lineItem.includes('rowc')) {
						// 顶部
						if (isSorption(selectHalfY, componentTopY)) {
							line.select.set(lineItem, { y: componentTopY });
							y = componentTopY - selectH / 2;
						}
						if (isSorption(selectHalfY, componentHalfY)) {
							line.select.set(lineItem, { y: componentHalfY });
							y = componentHalfY - selectH / 2;
						}
						if (isSorption(selectHalfY, componentBottomY)) {
							line.select.set(lineItem, { y: componentBottomY });
							y = componentBottomY - selectH / 2;
						}
					}
					if (lineItem.includes('rowb')) {
						// 顶部
						if (isSorption(selectBottomY, componentTopY)) {
							line.select.set(lineItem, { y: componentTopY });
							y = componentTopY - selectH;
						}
						if (isSorption(selectBottomY, componentHalfY)) {
							line.select.set(lineItem, { y: componentHalfY });
							y = componentHalfY - selectH;
							setComponentPosition(selectTarget.value, selectLeftX, componentHalfY - selectH);
						}
						if (isSorption(selectBottomY, componentBottomY)) {
							line.select.set(lineItem, { y: componentBottomY });
							y = componentBottomY - selectH;
						}
					}

					// 纵线对比的是 X
					if (lineItem.includes('coll')) {
						if (isSorption(selectLeftX, componentLeftX)) {
							line.select.set(lineItem, { x: componentLeftX });
							x = componentLeftX;
						}
						if (isSorption(selectLeftX, componentHalfX)) {
							line.select.set(lineItem, { x: componentHalfX });
							x = componentHalfX;
						}
						if (isSorption(selectLeftX, componentRightX)) {
							line.select.set(lineItem, { x: componentRightX });
							x = componentRightX;
						}
					}
					if (lineItem.includes('colc')) {
						if (isSorption(selectHalfX, componentLeftX)) {
							line.select.set(lineItem, { x: componentLeftX });
							x = componentLeftX - selectW / 2;
						}
						if (isSorption(selectHalfX, componentHalfX)) {
							line.select.set(lineItem, { x: componentHalfX });
							x = componentHalfX - selectW / 2;
						}
						if (isSorption(selectHalfX, componentRightX)) {
							line.select.set(lineItem, { x: componentRightX });
							x = componentRightX - selectW / 2;
						}
					}
					if (lineItem.includes('colr')) {
						if (isSorption(selectRightX, componentLeftX)) {
							line.select.set(lineItem, { x: componentLeftX });
							x = componentLeftX - selectW;
						}
						if (isSorption(selectRightX, componentHalfX)) {
							line.select.set(lineItem, { x: componentHalfX });
							x = componentHalfX - selectW;
						}
						if (isSorption(selectRightX, componentRightX)) {
							line.select.set(lineItem, { x: componentRightX });
							x = componentRightX - selectW;
						}
					}
				});
			});
			setComponentPosition(selectTarget.value, x, y);
		} catch (err) {
			console.log(err);
		}
	}, 200),
	{
		deep: true
	}
);

// * 取消对齐线
watch(
	() => $store.chart.editCanvas.isDrag,
	(val) => {
		if (!val) {
			line.select.clear();
		}
	}
);
</script>

<style lang="scss" scoped>
@include b(edit-align-line) {
	.line {
		z-index: 1;
		position: absolute;
		top: 0;
		left: 0;
		display: none;
		border: 1px solid var(--el-color-primary);
		opacity: 0.7;
		&.visible {
			display: block;
		}
	}
	.row {
		width: 100%;
	}
	.col {
		height: 100%;
	}
}
</style>
